﻿using System.Linq.Expressions;
using Basic.HrDAL.Model;
using Basic.HrModel.DB;
using Basic.HrModel.Emp;
using Basic.HrRemoteModel;
using Basic.HrRemoteModel.Emp.Model;
using SqlSugar;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.IdGenerator;
using WeDonekRpc.Model;
using WeDonekRpc.SqlSugar;

namespace Basic.HrDAL.Repository
{
    internal class EmpDAL : BasicDAL<DBEmpList, long>, IEmpDAL
    {
        public EmpDAL ( IRepository<DBEmpList> basicDAL ) : base(basicDAL)
        {
        }
        public void SetStatus ( long empId, HrEmpStatus status )
        {
            if ( !this._BasicDAL.Update(a => a.Status == status, a => a.EmpId == empId) )
            {
                throw new ErrorException("hr.emp.update.fail");
            }
        }
        public EmpSelectItem[] GetSelectItems ( SelectGetParam param )
        {
            return this._BasicDAL.Gets<EmpSelectItem>(param.ToWhere());
        }
        public Result[] GetEmps<Result> ( EmpGetParam getParam, Expression<Func<DBEmpList, Result>> selector )
        {
            return this._BasicDAL.Gets<Result>(getParam.ToWhere(), selector);
        }
        public Result[] GetEmps<Result> ( EmpGetParam getParam ) where Result : class, new()
        {
            return this._BasicDAL.Gets<Result>(getParam.ToWhere());
        }
        public Result[] Query<Result> ( EmpQuery query, IBasicPage paging, out int count ) where Result : class
        {
            paging.InitOrderBy("EmpId", true);
            return this._BasicDAL.Query<Result>(query.ToWhere(), paging, out count);
        }
        public void CheckPhone ( string phone )
        {
            if ( this._BasicDAL.IsExist(c => c.Phone == phone) )
            {
                throw new ErrorException("hr.emp.phone.repeat");
            }
        }
        public void CheckEmpNo ( string empNo )
        {
            if ( this._BasicDAL.IsExist(c => c.EmpNo == empNo) )
            {
                throw new ErrorException("hr.emp.no.repeat");
            }
        }

        public void CheckIDCard ( string idCard )
        {
            if ( this._BasicDAL.IsExist(c => c.IDCard == idCard) )
            {
                throw new ErrorException("hr.emp.idCard.repeat");
            }
        }
        public long Add ( EmpAdd data )
        {
            DBEmpList add = data.ConvertMap<EmpAdd, DBEmpList>();
            add.EmpId = IdentityHelper.CreateId();
            add.Status = HrEmpStatus.起草;
            add.RegTime = DateTime.Now;
            add.PwdLastUpdateTime = DateTime.Now;
            if ( data.PostCode.IsNull() && data.TitleCode.IsNull() )
            {
                base._BasicDAL.Insert(add);
            }
            else
            {
                ISqlQueue<DBEmpList> queue = this._BasicDAL.BeginQueue();
                queue.Insert(add);
                if ( !data.PostCode.IsNull() )
                {
                    queue.InsertBy<DBEmpPost>(data.PostCode.ConvertAll(a => new DBEmpPost
                    {
                        DeptId = data.DeptId,
                        CompanyId = data.CompanyId,
                        EmpId = add.EmpId,
                        Id = IdentityHelper.CreateId(),
                        PostCode = a,
                        UnitId = data.UnitId
                    }));
                }
                if ( !data.TitleCode.IsNull() )
                {
                    queue.InsertBy<DBEmpTitle>(data.TitleCode.ConvertAll(a => new DBEmpTitle
                    {
                        DeptId = data.DeptId,
                        CompanyId = data.CompanyId,
                        EmpId = add.EmpId,
                        Id = IdentityHelper.CreateId(),
                        TitleCode = a,
                        UnitId = data.UnitId
                    }));
                }
                _ = queue.Submit();
            }
            return add.EmpId;
        }
        public string[] Set ( DBEmpList soure, EmpSetDto set )
        {
            long deptId = soure.DeptId;
            string[] cols = soure.Merge(set);
            if ( cols.IsNull() )
            {
                return cols;
            }
            else if ( !soure.IsOpenAccount || deptId == set.DeptId )
            {
                if ( !this._BasicDAL.Update(soure, cols) )
                {
                    throw new ErrorException("hr.emp.set.fail");
                }
                return cols;
            }
            else
            {
                ISqlQueue<DBEmpList> queue = this._BasicDAL.BeginQueue();
                queue.Update(soure, cols);
                queue.DeleteBy<DBEmpDeptPower>(a => a.EmpId == soure.EmpId && a.DeptId == deptId);
                _ = queue.Submit();
                return cols;
            }
        }

        public void SetUserHead ( long empId, string head )
        {
            if ( !this._BasicDAL.Update(a => a.UserHead == head, a => a.EmpId == empId) )
            {
                throw new ErrorException("hr.emp.head.update.fail");
            }
        }
        public Dictionary<long, int> GetDeptEmpNum ( long[] deptId )
        {
            HrEmpStatus[] status = new HrEmpStatus[]
            {
                HrEmpStatus.起草,
                HrEmpStatus.启用
            };
            return this._BasicDAL.GroupBy(a => deptId.Contains(a.DeptId) && status.Contains(a.Status), a => a.DeptId, a => new
            {
                a.DeptId,
                num = SqlFunc.AggregateCount(a.DeptId)
            }).ToDictionary(a => a.DeptId, a => a.num);
        }
        public void SetPwd ( long empId, string pwd )
        {
            if ( !this._BasicDAL.Update(new DBEmpList
            {
                EmpId = empId,
                EmpPwd = pwd,
                PwdLastUpdateTime = DateTime.Now
            }, new string[] { "EmpPwd", "PwdLastUpdateTime" }) )
            {
                throw new ErrorException("hr.emp.pwd.update.fail");
            }
        }
        public void CheckEmail ( string email )
        {
            if ( this._BasicDAL.IsExist(c => c.Email == email) )
            {
                throw new ErrorException("hr.emp.email.repeat");
            }
        }
        public long[] SearchById ( EmpSearchArg query, int take, int index, out int count )
        {
            BasicPage paging = new BasicPage
            {
                Index = index,
                Size = take
            };
            paging.InitOrderBy("EmpId", false);
            return this._BasicDAL.Query(query.ToWhere(), a => a.EmpId, paging, out count);
        }
        public long[] SearchById ( EmpSearchArg query )
        {
            return this._BasicDAL.Gets(query.ToWhere(), a => a.EmpId);
        }
        public Result[] Search<Result> ( EmpGetQuery param ) where Result : class, new()
        {
            return this._BasicDAL.Gets<Result>(param.ToWhere());
        }

        public void SetEmpEntry ( DBEmpList soure, EmpEntrySet datum )
        {
            long companyId = soure.CompanyId;
            long deptId = soure.DeptId;
            string[] cols = soure.Merge(datum);
            ISqlQueue<DBEmpList> queue = this._BasicDAL.BeginQueue();
            if ( !cols.IsNull() )
            {
                queue.Update(soure, cols);
            }
            if ( soure.IsOpenAccount )
            {
                queue.DeleteBy<DBEmpDeptPower>(a => a.EmpId == soure.EmpId && a.DeptId == deptId);
            }
            if ( !datum.IsRetainTitle )
            {
                queue.DeleteBy<DBEmpTitle>(a => a.EmpId == soure.EmpId && a.CompanyId == companyId);
            }
            queue.DeleteBy<DBEmpPost>(a => a.EmpId == soure.EmpId && a.CompanyId == companyId);
            if ( !datum.Post.IsNull() )
            {
                queue.InsertBy<DBEmpPost>(datum.Post.ConvertAll(a => new DBEmpPost
                {
                    DeptId = datum.DeptId,
                    CompanyId = datum.CompanyId,
                    EmpId = soure.EmpId,
                    Id = IdentityHelper.CreateId(),
                    PostCode = a,
                    UnitId = datum.UnitId
                }));
            }
            if ( !datum.DropTitleId.IsNull() )
            {
                queue.DeleteBy<DBEmpTitle>(a => datum.DropTitleId.Contains(a.Id));
            }
            if ( !datum.Title.IsNull() )
            {
                queue.InsertBy<DBEmpTitle>(datum.Title.ConvertAll(a => new DBEmpTitle
                {
                    Id = IdentityHelper.CreateId(),
                    CompanyId = datum.CompanyId,
                    DeptId = datum.DeptId,
                    EmpId = soure.EmpId,
                    TitleCode = a,
                    UnitId = datum.UnitId
                }));
            }
            _ = queue.Submit();
        }

        public long[] FindEmpId ( EmpFindParam param )
        {
            return this._BasicDAL.Gets(param.ToWhere(), a => a.EmpId);
        }
    }
}
